home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1995 April / Internet Tools.iso / applic / ncsa / Mac / Telnet2.6 / prerelease / d5 / Telnet 2.6.1d5.src.sit.hqx / Telnet 2.6.1d5 src / source / parse / linemode.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-19  |  8.1 KB  |  267 lines

  1. /****************************************************************
  2. *    NCSA Telnet for the Macintosh                                *
  3. *                                                                *
  4. *    National Center for Supercomputing Applications                *
  5. *    Software Development Group                                    *
  6. *    152 Computing Applications Building                            *
  7. *    605 E. Springfield Ave.                                        *
  8. *    Champaign, IL  61820                                        *
  9. *                                                                *
  10. *    Copyright (c) 1986-1994,                                    *
  11. *    Board of Trustees of the University of Illinois                *
  12. ****************************************************************/
  13. #include <string.h>
  14. #include <stdio.h>
  15. #include "TelnetHeader.h"
  16. #include "wind.h"
  17. #include "parse.h"
  18.  
  19. #include "linemode.proto.h"
  20. #include "network.proto.h"
  21.  
  22. #ifdef MPW
  23. #pragma segment Parse
  24. #endif
  25.  
  26. //#define    OPTS_DEBUG
  27. #ifdef    OPTS_DEBUG
  28. #include "optsdebug.h"
  29. #define    opts_debug_print(x)    putln(x)    
  30. #else
  31. #define    opts_debug_print(x)
  32. #endif
  33.  
  34. static    void    DemangleLineMode(char *s, short mode);
  35. static    void    DemangleLineModeShort(char *s, short mode);
  36.  
  37. #define    SEND_NOSUPPORT_ON_SLC_INIT    1
  38.  
  39. static    unsigned char str_lm[] = { TEL_IAC, TEL_SB, N_LINEMODE, 0, 0, TEL_IAC, TEL_SE };
  40. static    unsigned char str_lm_mode[] = { TEL_IAC, TEL_SB, N_LINEMODE, L_MODE, 0, TEL_IAC, TEL_SE };
  41. void    linemode_suboption(struct WindRec *tw)
  42. {
  43.     short    i;
  44.     
  45.     switch(tw->parsedat[1]) {
  46.         char s[80];
  47.  
  48.         case L_MODE:    /* change mode */
  49. #ifdef OPTS_DEBUG
  50.             strcpy(s, "RECV: SB LINEMODE MODE => ");
  51.             DemangleLineModeShort(s, tw->parsedat[2]);
  52.             opts_debug_print(s);
  53. #endif
  54.             if (tw->lineAllow) {            // First make sure we allowed linemode in the first place.
  55.                 // RFC 1184 says client should ignore MODE negotiations with the MODE_ACK bit set, and should not
  56.                 //    generate a response if the negotiated MODE matches the current MODE
  57.                 if (!((tw->parsedat[2] & L_MODE_ACK) || ((tw->parsedat[2] & L_MODE_MASK) == tw->lmode))) {
  58.                 
  59.                     // This is a hack.  Accept the state of L_EDIT and L_TRAPSIG that the server wants.  If
  60.                     // the server only wants zero, one, two or both of those bits, generate an ack.  Otherwise
  61.                     // send the server a mode that masks out all requested bits except EDIT and TRAPSIG.
  62.                     
  63.                     // (Now, since we only support L_EDIT and/or L_TRAPSIG, if those are the only modes requested,)
  64.                     //    (send an ACK of that MODE to the server.)
  65.                     
  66.                     tw->lmode = (tw->parsedat[2] & (L_EDIT | L_TRAPSIG));    // Accept the mode.
  67.                     
  68.                     if ((tw->parsedat[2] & (L_EDIT | L_TRAPSIG)) == tw->parsedat[2]) {
  69.                         tw->parsedat[2] |= L_MODE_ACK;    // Set the MODE_ACK bit
  70.                         }
  71.                     // We got a MODE bit we dont support, mask out just what we support and send it back, UNacked.
  72.                     else {
  73.                         tw->parsedat[2] = tw->parsedat[2] & (L_EDIT | L_TRAPSIG);
  74.                         }
  75.  
  76.                     sprintf(s,"%c%c%c%c",IAC,TEL_SB,N_LINEMODE,L_MODE);
  77.                     netwrite(tw->port,s,4);
  78.                     sprintf(s,"%c%c%c",tw->parsedat[2],IAC,TEL_SE);
  79.                     netwrite(tw->port,s,3); 
  80. #ifdef OPTS_DEBUG
  81.                     opts_debug_print("SENT: IAC SB");
  82.                     strcpy(s, "SENT: LM MODE = ");
  83.                     DemangleLineModeShort(s, tw->parsedat[2]);
  84.                     opts_debug_print(s);
  85.                     opts_debug_print("SENT: IAC SE");
  86. #endif
  87.                 }
  88. #ifdef OPTS_DEBUG
  89.                 else {
  90.                     strcpy(s, "LINEMODE MODE = ");
  91.                     DemangleLineModeShort(s, tw->parsedat[2]);
  92.                     opts_debug_print(s);
  93.                     if (tw->parsedat[2] & L_MODE_ACK) 
  94.                         opts_debug_print("\tignored 'cause MODE_ACK was set.");
  95.                     else
  96.                         opts_debug_print("\tIMPLICITLY ACCEPTED.");
  97.                     strcpy(s, "Curr Linemode = ");
  98.                     DemangleLineModeShort(s, tw->lmode);
  99.                     opts_debug_print(s);
  100.                 }
  101. #endif
  102.                 
  103.             }
  104.             break;
  105.         
  106.         case TEL_DOTEL:    
  107. #ifdef OPTS_DEBUG
  108.             sprintf(munger,"RECV: SB LINEMODE DO %c", tw->parsedat[2]);
  109.             opts_debug_print(munger);
  110. #endif
  111.             str_lm[3] = TEL_WONTTEL;
  112.             str_lm[4] = tw->parsedat[2];
  113.             netpush(tw->port);
  114.             netwrite(tw->port, str_lm, sizeof(str_lm));
  115. #ifdef OPTS_DEBUG
  116.             sprintf(munger,"SENT: IAC SB LINEMODE DONT %c IAC SE", tw->parsedat[2]);
  117.             opts_debug_print(munger);
  118. #endif
  119.             break;
  120.  
  121.         case TEL_WILLTEL:
  122. #ifdef OPTS_DEBUG
  123.             sprintf(munger,"RECV: SB LINEMODE WILL %c", tw->parsedat[2]);
  124.             opts_debug_print(munger);
  125. #endif
  126.             str_lm[3] = TEL_DONTTEL;
  127.             str_lm[4] = tw->parsedat[2];
  128.             netpush(tw->port);
  129.             netwrite(tw->port, str_lm, sizeof(str_lm));
  130. #ifdef OPTS_DEBUG
  131.             sprintf(munger,"SENT: IAC SB LINEMODE DONT %c IAC SE", tw->parsedat[2]);
  132.             opts_debug_print(munger);
  133. #endif
  134.             break;
  135.  
  136.  
  137.         case L_SLC:        /* set local chars */
  138.             {
  139.             short    lmslcflag = 0;
  140. #ifdef OPTS_DEBUG
  141.             sprintf(munger,"RECV: SB LINEMODE SLC");
  142.             opts_debug_print(munger);
  143.             for(i=2;(tw->parsedat[i]!='\0') && (tw->parsedat[i]!=IAC); i+=3) {
  144.                 if(tw->parsedat[i+1] & SLC_AWK)
  145.                     sprintf(munger,"     %s %s|AWK %d",LMoptions[tw->parsedat[i]],LMflags[tw->parsedat[i+1] & SLC_LEVELBITS],tw->parsedat[i+2]);
  146.                 else
  147.                     sprintf(munger,"     %s %s %d",LMoptions[tw->parsedat[i]],LMflags[tw->parsedat[i+1] & SLC_LEVELBITS],tw->parsedat[i+2]);
  148.                 opts_debug_print(munger);
  149.     // 2.6b16.1            if ((unsigned char)(tw->parsedat[i+2])==IAC) i++;
  150.                 }    /* end for */
  151. #endif
  152.  
  153.             for (i=2, lmslcflag=0; (tw->parsedat[i]!='\0') && (tw->parsedat[i]!=IAC); i+=3) {
  154.  
  155.                 // If func = 0, skip it 'cause we are the client.
  156. //                                                    if (tw->parsedat[i] == 0)
  157. //                                                        continue;
  158.                 
  159.                 // If it's a function we don't know about, say we don't support it.  If the server is telling
  160.                 // us he doesn't support it, just ignore him.
  161.                 if (tw->parsedat[i] > SLC_MAX) {
  162.                     if ((tw->parsedat[i+1] & SLC_LEVELBITS) != SLC_NOSUPPORT) {
  163.                         if (!lmslcflag) {
  164.                             lmslcflag = 1;        // Do this only once
  165.                             sprintf(s,"%c%c%c%c",IAC,TEL_SB,N_LINEMODE,L_SLC);
  166.                             netwrite(tw->port,s,4);
  167.                             opts_debug_print("SENT: IAC SB LINEMODE SLC");
  168.                             }
  169.                         sprintf(s,"%c%c%c",tw->parsedat[i],SLC_NOSUPPORT,0);
  170. #ifdef OPTS_DEBUG
  171.                         sprintf(munger,"     %d SLC_NOSUPPORT 0",tw->parsedat[i]);
  172.                         opts_debug_print(munger);
  173. #endif
  174.                         netwrite(tw->port,s,3);
  175.                     }
  176.                     else
  177.                         continue;
  178.                 }
  179.                 
  180.                 // RFC 1184: If we get a response that is the same as the current setting, ignore it.  Technically, we
  181.                 //    should check the value for a CANTCHANGE response to satisfy part 2 of Sec 5.5.  However, since we
  182.                 //    advertised that key as CANTCHANGE in the first place, the server should not be changing it.  This
  183.                 //    should be fixed later, however I don't see it causing big problems right now. - JMB 12/93
  184.                 
  185.                 if (! ((((tw->parsedat[i+1] & SLC_LEVELBITS) == SLC_NOSUPPORT) && (tw->slc[tw->parsedat[i]] == -1))
  186.                     || (((tw->parsedat[i+1] & SLC_LEVELBITS) == SLC_CANTCHANGE) && (tw->slc[tw->parsedat[i]] != -1)))) {
  187.                     // If we get to this point, the value sent to us doesn't agree with what we want.
  188.                     
  189.                         
  190.                     if (!(tw->parsedat[i+1] & SLC_AWK)) {
  191.                         if (!lmslcflag) {
  192.                             lmslcflag = 1;        // Do this only once
  193.                             sprintf(s,"%c%c%c%c",IAC,TEL_SB,N_LINEMODE,L_SLC);
  194.                             netwrite(tw->port,s,4);
  195.                             opts_debug_print("SENT: IAC SB LINEMODE SLC");
  196.                             }
  197.                     
  198.                         if (tw->slc[tw->parsedat[i]]==-1)
  199.                             {
  200.                             sprintf(s,"%c%c%c",tw->parsedat[i],SLC_NOSUPPORT,0);
  201. #ifdef OPTS_DEBUG
  202.                             sprintf(munger,"     %s SLC_NOSUPPORT 0",LMoptions[tw->parsedat[i]]);
  203. #endif
  204.                             }
  205.                         else
  206.                             {
  207.                             sprintf(s,"%c%c%c",tw->parsedat[i],SLC_CANTCHANGE,(char)tw->slc[tw->parsedat[i]]);
  208. #ifdef OPTS_DEBUG
  209.                             sprintf(munger,"     %s SLC_CANTCHANGE %d",LMoptions[tw->parsedat[i]],
  210.                                                         (char)tw->slc[tw->parsedat[i]]);
  211. #endif
  212.                             }                                                                
  213. #ifdef OPTS_DEBUG
  214.                         opts_debug_print(munger);
  215. #endif
  216.                         netwrite(tw->port,s,3);
  217.     // 2.6b16.1                    if (tw->parsedat[i+2]==IAC) i++;
  218.                         }
  219.                     }
  220.                 }
  221.                 
  222.             if (lmslcflag) {
  223.                 sprintf(s,"%c%c",IAC,TEL_SE);
  224.                 netwrite(tw->port,s,2);
  225.                 }
  226.                 
  227.  
  228.                 /* otherwise just exit */
  229.                 }
  230.                 break;
  231.             
  232.             default:
  233. #ifdef OPTS_DEBUG
  234.                 sprintf(munger, "RECV: SB LINEMODE ?? (?? = %c)", tw->parsedat[1]);
  235.                 opts_debug_print(munger);
  236. #endif
  237.                 break;
  238.  
  239.             }
  240. }
  241.  
  242. static    void    DemangleLineMode(char *s, short mode)
  243. {
  244. #ifdef OPTS_DEBUG
  245.     short     i;
  246.     
  247.     for (i=0; i<5; i++) {
  248.         if (mode & (1 << i))
  249.             strcat(s, LMmodes[i]);
  250.     }
  251. #endif
  252. }
  253.  
  254. static    void    DemangleLineModeShort(char *s, short mode)
  255. {
  256. #ifdef OPTS_DEBUG
  257.     short     i;
  258.     
  259.     for (i=0; i<5; i++) {
  260.         if (mode & (1 << i))
  261.             strcat(s, LMmodeBits[i]);
  262.         else
  263.             strcat(s," ");
  264.     }
  265. #endif
  266. }
  267.